package com.appshelves;

import java.io.DataOutputStream;
import java.io.IOException;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

import com.appshelves.model.Model;
import com.appshelves.utils.ComponentHelper;
import com.appshelves.utils.Utils;
import com.appshelves.utils.Utils.WriteOperation;

public class PackageChangesReceiver extends BroadcastReceiver {

    public static final String CHANGES_FILE = "changes";
    public static final String ADDED_PACKAGE_PREFIX = "+";
    public static final String REMOVED_PACKAGE_PREFIX = "-";
    public static final int PREFIX_LENGTH = ADDED_PACKAGE_PREFIX.length();
    private static final int ACTION_NO_ACTION = -1;
    private static final int ACTION_ADD = 0;
    private static final int ACTION_REMOVE = 1;

    @Override
    public void onReceive(Context context, Intent intent) {
        String packageName = intent.getData().getSchemeSpecificPart();
        Utils.log(this, intent.getAction() + " " + packageName + " " + Model.isLoaded());

        Utils.setContextIfAbsent(context);

        int action = getAction(intent, packageName);
        if (action == ACTION_NO_ACTION)
            return;

        if (Model.isLoaded()) {
            notifyModel(packageName, action);
        } else
            storeChanges(context, packageName, action);
    }

    private int getAction(Intent intent, String packageName) {
        if (intent.getAction() == Intent.ACTION_PACKAGE_REMOVED) {
            if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) // only updating. It will be followed by ADDED intent
                return ACTION_NO_ACTION;
            return ACTION_REMOVE;
        }
        if (intent.getAction() == Intent.ACTION_PACKAGE_ADDED)
            return ACTION_ADD;
        return ComponentHelper.isPackageDisabled(packageName) ? ACTION_REMOVE : ACTION_ADD;
    }

    private void notifyModel(String packageName, int action) {
        if (action == ACTION_REMOVE)
            Model.deleteApp(packageName);
        else
            Model.updateOrAddApp(packageName);
    }

    private void storeChanges(Context context, String packageName, int action) {
        String prefix = action == ACTION_REMOVE ? REMOVED_PACKAGE_PREFIX : ADDED_PACKAGE_PREFIX;

        writeChanges(context, prefix + packageName);
    }

    private void writeChanges(Context context, final String changesString) {
        Utils.appendFile(context, CHANGES_FILE, new WriteOperation() {

            @Override
            public void run(DataOutputStream stream) throws IOException {
                stream.writeUTF(changesString);
                stream.writeLong(System.currentTimeMillis());
            }

            @Override
            public void onFail() {
            }
        });
    }
}
